package cn.sccl.dirms.security.service.impl;

import cn.sccl.common.dao.BaseDAO;
import cn.sccl.common.service.impl.BaseManagerImpl;
import cn.sccl.common.util.Const;
import cn.sccl.common.util.DataBaseUtils;
import cn.sccl.common.util.PropertiesUtil;
import cn.sccl.dirms.security.dao.AuthorityDAO;
import cn.sccl.dirms.security.model.Authority;
import cn.sccl.dirms.security.model.MenuAction;
import cn.sccl.dirms.security.service.AuthorityManager;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * Created by 杨浩宇 on 2016-02-24.
 */
@Service
public class AuthorityManagerImpl extends BaseManagerImpl<Authority> implements AuthorityManager {
    private static final String ADMIN = "admin";

    @Autowired
    private AuthorityDAO authorityDAO;

    public AuthorityDAO getAuthorityDAO() {
        return authorityDAO;
    }

    @Override
    public BaseDAO<Authority> getBaseDAO() {
        return getAuthorityDAO();
    }

    /**
     * 根据用户ID查询具有的导航菜单
     *
     * @return
     */
    @Override
    public List<Authority> findNavAuthoritesByUser(String userId) {
        // for oracle
        if (PropertiesUtil.getString("jdbc.type").equals(Const.ORACLE)) {
            String sql = "select *\n" +
                    "  from (select distinct t.*\n" +
                    "          from t_sec_authorities         t,\n" +
                    "               t_sec_users_roles       ru,\n" +
                    "               t_sec_roles_authorities ra\n" +
                    "         where t.id = ra.authority_id\n" +
                    "           and ru.role_id = ra.role_id\n" +
                    "           and t.delete_flag = ru.delete_flag\n" +
                    "           and t.delete_flag = ra.delete_flag\n" +
                    "           and t.delete_flag = 0\n" +
                    "           and ru.user_id = ?) tp\n" +
                    " where tp.parent_self is not null\n" +
                    "        and tp.auth_type = 1\n" +
                    "        and tp.active = 1\n" +
                    "connect by prior tp.id = tp.parent_self\n" +
                    " start with tp.parent_self is null\n" +
                    " order siblings by tp.auth_index";

            List<Authority> authorityList = new ArrayList<Authority>();
            authorityList = getDataBase().query4Model(sql, Authority.class, new Object[]{userId});
            Collections.sort(authorityList);
            authorityList = reorganizeMenusToTree(authorityList);
            return authorityList;
        } else {
            // for mysql
            String sql = "select distinct t.*\n" +
                    "      from t_sec_authorities         t,\n" +
                    "      t_sec_users_roles       ru,\n" +
                    "      t_sec_roles_authorities ra\n" +
                    "      where t.id = ra.authority_id\n" +
                    "      and ru.role_id = ra.role_id\n" +
                    "      and t.delete_flag = ru.delete_flag\n" +
                    "      and t.delete_flag = ra.delete_flag\n" +
                    "      and t.delete_flag = 0\n" +
                    "      and t.auth_type = 1\n" +
                    "      and t.active = 1\n" +
                    "      and t.parent_self is null" +
                    "      and ru.user_id = ?";

            List<Authority> authorities = new ArrayList<Authority>();
            // 注释：为了测试
            //获取顶级菜单
            List<Authority> rootList = getDataBase().query4Model(sql, Authority.class, new Object[]{userId});
            List<Authority> result = new ArrayList<Authority>();

            //获取顶级菜单下的所有菜单
            reorganizeMenus(userId, rootList, result);
//                if (!result.isEmpty()) {
//                    result.remove(0);
//                }
            authorities = reorganizeMenusToTree(result);
            if(authorities != null){
                Collections.sort(authorities, new Comparator<Authority>() {
                    @Override
                    public int compare(Authority o1, Authority o2) {
                        if(o1.getAuthIndex() == null){
                            return -1;
                        }
                        if(o2.getAuthIndex() == null){
                            return -1;
                        }
                        if(o1.getAuthIndex().compareTo(o2.getAuthIndex()) == 0){
                            if(o1.getCreateTime() == null){
                                return -1;
                            }
                            if(o2.getCreateTime() == null){
                                return -1;
                            }
                            if(o1.getCreateTime().getTime() - o2.getCreateTime().getTime() > 0){
                                return 1;
                            }else if(o1.getCreateTime().getTime() - o2.getCreateTime().getTime() < 0){
                                return -1;
                            }
                            return 0;
                        }
                        return o1.getAuthIndex().compareTo(o2.getAuthIndex());
                    }
                });
            }
            return authorities;
        }
    }

    @Override
    public List<Authority> findByUser(String userId,String name) {
        // for oracle
        if (PropertiesUtil.getString("jdbc.type").equals(Const.ORACLE)) {
            String sql = "select *\n" +
                    "  from (select distinct t.*\n" +
                    "          from t_sec_authorities         t,\n" +
                    "               t_sec_users_roles       ru,\n" +
                    "               t_sec_roles_authorities ra\n" +
                    "         where t.id = ra.authority_id\n" +
                    "           and ru.role_id = ra.role_id\n" +
                    "           and t.delete_flag = ru.delete_flag\n" +
                    "           and t.delete_flag = ra.delete_flag\n" +
                    "           and t.delete_flag = 0\n" +
                    "           and ru.user_id = ?) tp\n" +
                    "   where 1=1                       " +
                    "    and tp.delete_flag = 0" +
//                " where tp.parent_self is not null\n" +
//                "        and tp.auth_type = 2\n" +
                    "        and tp.active = 1\n" +
                    "connect by prior tp.id = tp.parent_self\n" +
                    " start with tp.parent_self is null\n" +
                    " order siblings by tp.auth_index";

            List<Authority> authorityList = new ArrayList<Authority>();
            if (userId != null)
            {
                if (ADMIN.equals(name)) { //如果是默认admin用户,则初始给全部菜单,否则需要根据权限来取菜单.
                    sql = "select distinct tp.* from t_sec_authorities         tp\n" +
                            " where 1=1\n" +
                            " and tp.active = 1\n" +
                            "    and tp.delete_flag = 0\n" +
                            " connect by prior tp.id = tp.parent_self\n" +
                            " start with tp.parent_self is null\n" +
                            " order siblings by tp.auth_index";
                    authorityList = getDataBase().query4Model(sql, Authority.class);
                } else {
                    authorityList = getDataBase().query4Model(sql, Authority.class, new Object[]{userId});
                }

                Collections.sort(authorityList);
                authorityList = reorganizeMenusToTree(authorityList);
            }
            return authorityList;
        } else {
            // for mysql
            String sql = "select distinct t.*\n" +
                    "      from t_sec_authorities         t,\n" +
                    "      t_sec_users_roles       ru,\n" +
                    "      t_sec_roles_authorities ra\n" +
                    "      where t.id = ra.authority_id\n" +
                    "      and ru.role_id = ra.role_id\n" +
                    "      and t.delete_flag = ru.delete_flag\n" +
                    "      and t.delete_flag = ra.delete_flag\n" +
                    "      and t.delete_flag = 0\n" +
                    "      and t.active = 1\n" +
                    "      and t.parent_self is null\n" +
                    "      and ru.user_id = ?";

            List<Authority> authorityList = new ArrayList<Authority>();
            List<Authority> resultList = new ArrayList<Authority>();
            List<Authority> result = new ArrayList<Authority>();

            if (userId != null) {
                if (ADMIN.equals(name)) { //如果是默认admin用户,则初始给全部菜单,否则需要根据权限来取菜单.
                    sql = "select distinct t.*\n" +
                            "      from t_sec_authorities         t\n" +
                            "      where 1=1 and t.delete_flag = 0\n" +
                            "      and t.active = 1 \n" +
                            "      and t.parent_self is null";
                    authorityList = getDataBase().query4Model(sql, Authority.class);
                    reorganizeMenus(authorityList, result);
                    resultList = reorganizeMenusToTree(result);
                } else {
                    authorityList = getDataBase().query4Model(sql, Authority.class, new Object[]{userId});
                    reorganizeMenus(userId, authorityList, result);
                    resultList = reorganizeMenusToTree(result);
                }
            }
            return resultList;
        }
    }

    @Override
    public List<Authority> findAllUrlNotNull() {
        String sql = "select * from t_sec_authorities t   where t.auth_url is not null";
        List<Authority> authorityList = getDataBase().query4Model(sql, Authority.class);
        return authorityList;
    }

    @Override
    public List<Authority> findByUserId(String userId) {
        String sql =
                "select distinct a.*\n" +
                        "  from t_sec_authorities         a,\n" +
                        "       t_sec_roles_authorities ra,\n" +
                        "       t_sec_users_roles       ur\n" +
                        " where a.auth_url is not null\n" +
                        "   and a.delete_flag = ra.delete_flag\n" +
                        "   and a.delete_flag = ur.delete_flag\n" +
                        "   and a.delete_flag = 0\n" +
                        "   and ur.role_id = ra.role_id\n" +
                        "   and ra.authority_id = a.id\n" +
                        "   and ur.user_id = ?";
        List<Authority> authorityList = getDataBase().query4Model(sql, Authority.class, new Object[]{userId});
        Collections.sort(authorityList);//
        return authorityList;
    }


    @Override
    public List<Authority> findBySence(String userId,String sence) {
        String sql =
                "select distinct a.*\n" +
                        "  from t_sec_authorities         a,\n" +
                        "       t_sec_roles_authorities ra,\n" +
                        "       t_sec_users_roles       ur\n" +
                        " where a.auth_url is not null\n" +
                        "   and ur.role_id = ra.role_id\n" +
                        "   and ra.authority_id = a.id\n" +
                        "   and a.delete_flag = ra.delete_flag\n" +
                        "   and a.delete_flag = ur.delete_flag\n" +
                        "   and a.delete_flag = 0\n" +
                        "   and ur.user_id = ?\n" +
                        "  and a.sence =?\n" +
                        " order by a.auth_index";
        if (userId != null) {
            List<Authority> authorityList = getDataBase().query4Model(sql, Authority.class, new Object[]{userId, sence});
            return authorityList;
        } else {
            return new ArrayList<Authority>();
        }

    }

    /**
     * 整理菜单，将普通列表整理成菜单树
     *
     * @param menuActions
     * @return
     */
    private List<Authority> reorganizeMenusToTree(List<Authority> menuActions) {
        List<Authority> topMenus = new ArrayList<Authority>();
        if (menuActions == null) {
            return topMenus;
        }

        boolean findParent = false;
        for (Authority ma : menuActions) {
            findParent = false;
            // 查找父亲
            for (Authority menuAction : menuActions) {
                if (ma.getParentSelf() != null && ma.getParentSelf().equals(menuAction.getId())) {
                    if (menuAction.getChildren() == null) {
                        menuAction.setChildren(new ArrayList<Authority>());
                    }
                    menuAction.getChildren().add(ma);
                    findParent = true;
                    break;
                }
            }
            if (!findParent) {
                topMenus.add(ma);
            }
        }

        return topMenus;
    }

    // for mysql
    /**
     * 组织菜单
     * @param userId
     * @param parentList
     * @param result
     */
    private void reorganizeMenus(String userId, List<Authority> parentList, List<Authority> result) {
        String sql = "SELECT\n" +
                "t.*\n" +
                "FROM\n" +
                "t_sec_authorities t,\n" +
                "t_sec_users_roles ru,\n" +
                "t_sec_roles_authorities ra\n" +
                "WHERE t.id = ra.authority_id\n" +
                "AND ru.role_id = ra.role_id\n" +
                "AND t.delete_flag = ru.delete_flag\n" +
                "AND t.delete_flag = ra.delete_flag\n" +
                "AND t.delete_flag = 0\n" +
                "AND t.active = 1\n" +
                "AND FIND_IN_SET(t.parent_self, getAuthChildList(?)) AND t.id <> ?\n" +
                "AND t.delete_flag = 0\n" +
                "AND t.active = 1\n" +
                "AND ru.user_id = ?\n" +
                "ORDER BY t.auth_index ,t.create_time";
        for (Authority parentAu: parentList) {
            List<Authority> List = getDataBase().query4Model(sql, Authority.class, new Object[]{parentAu.getId(),parentAu.getId(),userId});
            for(Authority a:List){
               if(!result.contains(a)){
                   result.add(a);
               }
            }
//            result.addAll(List);
        }

    }

    /**
     * 组织菜单
     * @param parentList
     * @param result
     */
    private void reorganizeMenus(List<Authority> parentList, List<Authority> result) {
        String sql = "select distinct t.*\n" +
                "      from t_sec_authorities         t\n" +
                "      where 1=1 and t.delete_flag = 0\n" +
                "      and t.active = 1\n" +
                "      and t.parent_self = ?";
        for (Authority parentAu: parentList) {
            result.add(parentAu);
            List<Authority> rootList = getDataBase().query4Model(sql, Authority.class, new Object[]{parentAu.getId()});
            if (!rootList.isEmpty()) {
                reorganizeMenus(rootList, result);
            }
        }

    }

    /**
     * all组织菜单
     * @param parentList
     * @param result
     */
    private void reorganizeAllMenus(List<Authority> parentList, List<Authority> result) {
        String sql = "select distinct t.*\n" +
                "      from t_sec_authorities         t\n" +
                "      where 1=1 and t.delete_flag = 0\n" +
                "      and t.parent_self = ?";
        for (Authority parentAu: parentList) {
            result.add(parentAu);
            List<Authority> rootList = getDataBase().query4Model(sql, Authority.class, new Object[]{parentAu.getId()});
            if (!rootList.isEmpty()) {
                reorganizeAllMenus(rootList, result);
            }
        }

    }

    @Override
    public List<MenuAction> findChildren(String parentId) {
        Authority authority = new Authority();
        authority.setParentSelf(parentId);
        HashMap<String, Object> map = DataBaseUtils.Model2HashMap(authority, new String[]{"parentSelf"});
        String sql =
                "select a.*,\n" +
                        "       (select count(1) from t_sec_authorities c where c.parent_self = a.id and c.delete_flag = 0) children_count\n" +
                        "  from t_sec_authorities a\n" +
                        " where a.delete_flag = 0\n";
        Object[] params;
        if (StringUtils.isBlank(parentId)) {
            sql += " and a.parent_self is null";
            params = new Object[]{};
        } else {
            sql += " and a.parent_self = ?";
            params = new Object[]{parentId};
        }
        sql += " order by a.auth_index";
        return this.getDataBase().query4Model(sql, MenuAction.class, params);
    }

    @Override
    public List<Authority> findAll() {
        List<Authority> authorityList = new ArrayList<Authority>();
        List<Authority> resultList = new ArrayList<Authority>();
        List<Authority> result = new ArrayList<Authority>();
        String sql = "select distinct t.*\n" +
                "      from t_sec_authorities         t\n" +
                "      where 1=1 and t.delete_flag = 0\n" +
                "      and t.parent_self is null";
        authorityList = getDataBase().query4Model(sql, Authority.class);
        reorganizeAllMenus(authorityList, result);
        resultList = reorganizeMenusToTree(result);

        return resultList;
    }

    @Override
    public Authority findSingleByAuthorityName(String name) {
        String sql ="select a.* from t_sec_authorities a " +
                "where 1=1 and a.delete_flag = 0 and a.name=? ";


        return null;
    }
}